;  THIS IS A PROGRAM TO FORMAT CPM DISKS USEING A VERSAFLOPPY II DISK 
;  CONTROLLER. NOTE IT IS SELF A CONTAINED PROGRAM (EXCEPT FOR CONSOLE I/O)
;  IT DOES NOT REQUIRE THE ROM BIOS TO FORMAT A DISK.
;
;	JOHN MONAHAN		5/21/81		VERSION	0.0
;
;
;
NBYTES	EQU	128	;BYTES PER SECTOR (*2 FOR 256 BYTE SECTORS)
LF	EQU	0AH
CR	EQU	0DH
BELL	EQU	07H
CLEAR	EQU	1AH
TAB	EQU	09H
;
CI	EQU	0F003H	;CONSOLE INPUT
CO	EQU	0F009H	;CONSOLE OUTPUT
;	
TADDR	EQU	40H	;STORE FOR DMA ADDRESS
UNIT	EQU	42H	;NEW UNIT BYTE
SCTR	EQU	43H	;SECTOR
TRK	EQU	44H	;TRACK
ERMASK	EQU	46H	;ERROR MASK
ERSTAT	EQU	47H	;PRESENT ERROR STORE
CMDSV	EQU	4EH	;COMMAND SAVE
SPSV	EQU	4FH	;SP SAVE
TEMP2	EQU	51H	;2 BYTE TEMP RECORD
UNITCK	EQU	55H	;OLD UNIT BYTE
SSTACK	EQU	80H	;SYSTEM STACK
COLD	EQU	80H	;COLD START ADDRESS
;
;	PORTS FOR 1791
RSET	EQU	60H		;CONTROLLER RESET ADDRESS
SELECT	EQU	63H		;DRIVE SELECT PORT
STATUS	EQU	64H		;STATUS PORT
TRACK	EQU	65H		;TRACK PORT
SECTOR	EQU	66H		;SECTOR PORT
DATA	EQU	67H		;DATA PORT
CMD	EQU	64H		;COMMAND PORT
;
RDACMD	EQU	0C0H		;READ ADDRESS CODE
RDCMD	EQU	088H		;READ SECTOR CODE
WRCMD	EQU	0A8H		;WRITE SECTOR CODE
WRTCMD	EQU	0F4H		;WRITE TRACK CODE
;
;
;	EQUATES FOR [IX] REGISTRAR
;
NSCTRS	EQU	0
HEADR	EQU	1
GAP1	EQU	2
GAP2	EQU	3
GAP3	EQU	4
RSCMD	EQU	5
SKNCMD	EQU	6
SKCMD	EQU	7
;
;------------------------------------------------------------------------------
	ORG	100H
;
START:	LD	SP,STACK
	LD	A,(UNIT)	;GET TYPE OF CURRENT A: DRIVE
	LD	(TEMP),A
AGAIN:	LD	HL,OMSG
	CALL	PMSG
	LD	A,77		;DEFALT OF 77 TRACKS /DISK
	LD	(TRKNO),A
	CALL	TABLEX		;FIND OUT WHAT IS WANTED
	JP	NZ,DONE
	LD	A,B
	LD	(UNIT),A
	CALL	FMAT
	JR	NZ,ERROR
	LD	HL,ENDMSG
	CALL	PMSG
	JP	AGAIN
DONE:	LD	A,(TEMP)
	LD	(UNIT),A
	JP	0		;RETURN TO CPM
;
ERROR:	LD	HL,ERRMSG
	CALL	PMSG
	JR	DONE
;
PMSG	LD	A,(HL)		;PRINT MESSAGE STRING
	OR	A
	RET	Z
	LD	C,A
	CALL	CO
	INC	HL
	JP	PMSG
;
TABLEX:	CALL	CI		;GET FIRST CHARACTER
	PUSH	AF
	LD	C,A
	CALL	CO
	POP	AF
	CP	'D'		;MUST WANT DD 8"
	LD	B,41H
	RET	Z
	CP	'S'		;MUST WANT SD 8"
	LD	B,01H
	RET	Z
	CP	'X'		;IS SYSTEM TRACK FORMAT REQ
	LD	A,0
	RET	NZ		;RETURN IF NONE OF THE ABOVE
	LD	A,2		;SET TO FORMAT ONLY TWO TRACKS
	LD	(TRKNO),A
	JP	TABLEX
;	
;
;
;**************** DISK FORMAT ROUTINE *****************************************
;
FMAT:	CALL	UNITFX
	LD	(TEMP2),SP
	PUSH	IY
	PUSH	IX
	PUSH	HL
	LD	HL,800H
	LD	(TADDR),HL
	LD	(SPSV),SP
	POP	HL
	CALL	DRVSET
	PUSH	AF		;SWITCH ON DRIVE & LET IT GET UP TO SPEED
	LD	A,00001001B	;SEND A HEAD LOAD SIGNAL
	OUT	(CMD),A
	LD	A,0FFH
	CALL	DELAY1
	POP	AF
	CALL	Z,HOME1
	JR	NZ,ERXIT  
	CALL	SCTRIM
	CALL	TRCKIM
	XOR	A
IDSET:	CALL	SETID
	PUSH	BC
	CALL	FMAT1
	CALL	NXTRK
	POP	BC
	JR	NZ,FINISH
	PUSH	DE		;---
	LD	D,A		;---
	LD	A,(TRKNO)	;---
	CP	D		;---
	LD	A,D		;---
	POP	DE  		;---
;	CP	(IX+NTRKS)
	JR	NZ,IDSET  
FINISH:	POP	IX
	POP	IY
	RET
;
ERXIT:	POP	IX
	LD	SP,(TEMP2)
	RET
;
;*********** SECTOR IMAGE ROUTINE *******************
SCTRIM:	LD	HL,(TADDR)
	LD	A,(IX+GAP2)
	RRCA
	LD	A,4EH
	JP	NC,HEADER
	LD	A,0FFH
HEADER:	LD	E,A
	LD	B,(IX+HEADR)
	CALL	IMBLD
	LD	B,(IX+GAP3)
	CALL	IMBLD
	XOR	A
	LD	B,(IX+GAP1)
	CALL	IMBLD
	CALL	MRKCHK
IDMARK:	LD	A,0FEH
	LD	(HL),A
	INC	HL
	PUSH	HL
	EXX
	POP	DE
	EXX
	XOR	A
	LD	B,4
	CALL	IMBLD
	LD	A,0F7H
	LD	(HL),A
	INC	HL
	LD	B,(IX+GAP2)
	LD	A,B
	SRL	A
	INC	A
	LD	C,A
	LD	A,E
	CALL	IMBLD
	LD	B,C
	XOR	A
	CALL	IMBLD
	CALL	MRKCHK
	LD	A,0FBH
	LD	(HL),A
	INC	HL
	LD	B,128
	LD	A,(UNIT)
	RLCA
	JR	NC,IDM
	LD	B,0
IDM:	LD	A,0E5H
	CALL	IMBLD
	LD	A,0F7H
	LD	(HL),A
	INC	HL
	RET
;
MRKCHK:	LD	A,E
	OR	A
	RET	M
	LD	A,0F5H
	LD	B,3
;
IMBLD:	LD	(HL),A
	INC	HL
	DJNZ	IMBLD
	RET
;
;********* TRACK IMAGE ROUTINE ******************
TRCKIM:	EXX
	LD	B,(IX+NSCTRS)
	DEC	B
	EXX
	LD	DE,(TADDR)
	PUSH	HL
	OR	A
	LD	C,(IX+HEADR)
	LD	B,0
	EX	DE,HL
	ADD	HL,BC
	EX	DE,HL
	SBC	HL,DE
	PUSH	HL
	POP	BC
	POP	HL
	PUSH	BC
	EX	DE,HL
	EXX
BLDTRK:	EXX
	LDIR
	POP	BC
	PUSH	BC
	EXX
	DJNZ	BLDTRK  
	EXX
	POP	BC
	EX	DE,HL			;NOTE SIDECK: HAS BEEN REMOVED
	XOR	A
SCHK1:	LD	L,A			;(NOT NEEDED WILL DO ONLY SINGLE SIDE)
	LD	H,L			;[H]=0 FOR SIDE NO
	RET
;
;******* SECTOR ID ROUTINE **************
SETID:	PUSH	HL
	PUSH	BC
	EXX
	POP	BC
	POP	HL
	PUSH	DE
	POP	IY
	PUSH	DE
	EX	AF,AF'
	LD	D,1
	LD	A,(IX+NSCTRS)
	CP	26
	LD	A,1
	JR	Z,ID1 
	LD	A,(IX+NSCTRS)
	SRL	A
	INC	A
	JR	NC,ID2  
ID1:	EX	AF,AF'
	LD	(IY),A			;PUT TRACK # @ [IY]
	LD	(IY+1),H		;SIDE NO @ [IY+2]
ID1A:	EX	AF,AF'
	LD	(IY+2),A
	PUSH	AF
	LD	A,(UNIT)
	RLCA
	JR	NC,ID4
	LD	A,1
	LD	(IY+3),A
ID4:	POP	AF
	CP	(IX+NSCTRS)
	JR	Z,ID3  
	ADD	IY,BC
	INC	A
ID2:	LD	E,A			;TEMPORLY STORE SECTOR COUNT
	LD	A,26
	CP	(IX+NSCTRS)
	LD	A,E			;GET SECTOR COUNT BACK
	JR	Z,ID1
	LD	A,D
	LD	D,E
	JR	ID1  
ID3:	EX	AF,AF'
	POP	DE
	EXX
	RET
;
; ********** DISK FORMAT WRITE ************
FMAT1:	PUSH	DE
	PUSH	BC
	EXX
	EX	AF,AF'
	POP	BC
	PUSH	DE
	LD	E,A
	LD	D,C
	LD	B,(IX+HEADR)
	LD	C,DATA
	LD	HL,(TADDR)
	LD	A,80H
	LD	(ERMASK),A
	CALL	SWEB
	LD	A,(UNIT)
	RLCA
	LD	A,0
	JR	NC,FMAT3
	LD	A,1
FMAT3:	LD	(TEMP1),A
	LD	A,WRTCMD
	LD	(CMDSV),A
	DI
	OUT	(CMD),A
	LD	A,(TEMP1)
	OTIR
	LD	B,D
FMAT5:	OTIR
	OR	A
	JR	Z,FMAT4
	OTIR
FMAT4:	LD	B,D
	DEC	E
	JR	NZ,FMAT5
	POP	DE
	POP	HL
	LD	A,(HL)
OY2:	OUT	(C),A
	DJNZ	OY2
	EI
	EXX
	EX	AF,AF'
	RET
;
;
NXTRK:	EX	AF,AF'
	LD	A,47
DEL1:	DJNZ	DEL1
	DEC	A
	JR	NZ,DEL1  
	IN	A,(SELECT)
	OR	80H
	OUT	(SELECT),A
	EX	AF,AF'
	INC	A
	PUSH	DE		;---
	LD	D,A		;---
	LD	A,(TRKNO)	;---
	CP	D		;---
	LD	A,D		;---
	POP	DE		;---
	RET	Z
	LD	(TRK),A
	PUSH	HL
	LD	(SPSV),SP
	POP	HL
E0:	DJNZ	E0
	EXX
	EX	DE,HL
	LD	A,(IX+SKNCMD)
	CALL	SEEK4
	EX	DE,HL
	EXX
	IN	A,(TRACK)
	LD	B,A
	LD	A,(TRK)
	CP	B
	LD	B,0
	RET
;
;
;
;	SEND A RESTORE TO DISK
HOME1:	LD	(SPSV),SP
	LD	A,(IX+RSCMD)
	CALL	SEEK4
	XOR	A
	RET
;
;	CHECK DRIVE SELECT & CHANGE IF DIFFERENT
DRVSET:LD	DE,UNIT
	LD	A,(DE)
	AND	0E0H
	LD	C,A
	LD	A,(DE)
	AND	03
	LD	B,A
	LD	A,1
	JR	Z,DRVSEL  
CKDRV1:	RLCA
	DJNZ	CKDRV1  
DRVSEL:	OR	C
	AND	7FH
	LD	B,A
	LD	A,C
	LD	IX,STDSDT
	CP	0
	JR	Z,CKDRV  
	LD	IX,STDDDT
	CP	40H
	JR	Z,CKDRV  
	LD	IX,DDT256
CKDRV:	LD	(IXSAV),IX
	PUSH	BC
DRVST:	POP	AF
	CPL
	OUT	(SELECT),A
	LD	A,(DE)
	LD	(UNITCK),A
	CALL	DELAY
RDYCK:	IN	A,(STATUS)
	AND	80H
	JP	NZ,END2
	RET
;
;
DELAY:	LD	A,(UNIT)
	BIT	5,A
	LD	A,39
	JR	Z,DELAY1  
	LD	A,60
DELAY1:	LD	B,0
M0:	DJNZ	M0
	DEC	A
	JR	NZ,DELAY1  
	RET
;
;
END:	CALL	WAIT
	IN	A,(STATUS)
	LD	D,A
	LD	A,(ERMASK)
	AND	D
	RET	Z
END1:	LD	A,D
END2:	LD	(ERSTAT),A
	CALL	DELAY
	OR	1
	LD	SP,(SPSV)
	CALL	UNITFX
	RET
;
;
;	SEEK TRACK
SEEK4:	LD	(CMDSV),A
	LD	B,210
S0:	DJNZ	S0
	CALL	WAIT
	LD	A,(TRK)
	OUT	(DATA),A
	LD	A,80H
	LD	(ERMASK),A
	LD	A,(CMDSV)
	OUT	(CMD),A
	LD	B,10
D0:	DJNZ	D0
	CALL	END
	CALL	DELAY
	LD	A,(CMDSV)
	CP	(IX+RSCMD)
	RET	Z
	IN	A,(STATUS)
	AND	10H
	JR	NZ,SEEK2
	IN	A,(TRACK)
	CP	C
	RET	Z
SEEK2:	LD	A,20H
END2JP:	JR	END2  
;
WAIT:	LD	E,0
	PUSH	BC
	LD	C,2
WAIT2:	IN	A,(STATUS)
	AND	1
	JR	Z,DWAIT
	DJNZ	WAIT2  
	DEC	E
	JR	NZ,WAIT2
	DEC	C
	JR	NZ,WAIT2
	POP	BC  
	IN	A,(SELECT)
	OR	80H
	OUT	(RSET),A
F0:	DJNZ	F0
	IN	A,(RSET)
	CALL	FRCINT
	LD	A,(IX+RSCMD)
	CALL	SEEK4
	LD	A,0FEH
	JP	END2JP	
;
;	DISABLE WAIT STATES
DWAIT:	POP	BC
	IN	A,(SELECT)
	OR	80H
	OUT	(SELECT),A
	RET
;
;	ENABLE WAIT STATES
SWEB:	IN	A,(SELECT)
	AND	7FH
	OUT	(SELECT),A
	RET
;
;
;	FORCE CHIP INTERUPT
FRCINT:	LD	A,0D0H
	OUT	(CMD),A
	LD	A,10
FRC1:	DEC	A
	JR	NZ,FRC1
	IN	A,(STATUS)
	RET
;
;
UNITFX:	LD	A,0FFH
	LD	(UNITCK),A
	RET
;
;
;------	NOTE 15H & 11H TURN ON UNDERLINE ON SD VIDIO BOARD MAY WANT TO CHANGE--
;
OMSG	DB	CR,LF,LF
	DB	'Enter a one letter code indicating drive density',CR,LF
	DB	'Note a prefix of X before D or S means format system '
	db	'tracks only.',CR,LF
	DB	'Enter CR when finished',CR,LF,LF
	DB	'S = ',15H,'SINGLE',11H,' DENSITY      D = '
	DB	15H,'DOUBLE',11H,' DENSITY',CR,LF,0
ENDMSG:	DB	CR,LF,BELL,'Disk has been formatted ',CR,LF,0
ERRMSG:	DB	CR,LF,BELL,'SORRY COULD NOT SEEK NEXT TRACK',CR,LF,0
;
;
;	LOOKUP TABLES OF DISK PARAMETERS
;
;	8" SINGLE DENSITY DRIVE VARIABLES
STDSDT:	DEFB	26	;SECTORS PER TRACK
;	DEFB	77	;TRACKS PER SIDE
	DEFB	100-27	;INDEX HEADER GAP
	DEFB	6	;GAP 1
	DEFB	11	;GAP 2
	DEFB	27	;GAP 3
	DEFB	9	;RESTORE CODE
	DEFB	19H	;SEEK NO VERIFY CODE
	DEFB	1DH	;SEEK WITH VERIFY
;	
;	8" DOUBLE DENSITY (128 BYTE SECTORS)
STDDDT:	DEFB	50	;SECTORS PER TRACK
;	DEFB	77	;TRACKS PER SIDE
	DEFB	100-16	;HEADER GAP
	DEFB	8	;GAP 1
	DEFB	22	;GAP 2
	DEFB	16	;GAP 3
	DEFB	9	;RESTORE CODE
	DEFB	19H	;SEEK NO VERIFY
	DEFB	1DH	;SEEK WITH VERIFY
;
;	8" DOUBLE DENSITY (256 BYTE SECTORS) ----NOTE THIS FORMAT IS UNTESTED
DDT256:	DEFB	26	;NBR SECTORS PER TRACK
;	DEFB	77	;NBR TRACKS PER SIDE
	DEFB	100-54	;INDEX HEADER GAP
	DEFB	8	;NBR GAP 1
	DEFB	22	;NBR GAP 2
	DEFB	54	;NBR GAP 3
	DEFB	9	;RESTORE CODE
	DEFB	19H	;SEEK NO VERIFY
	DEFB	1DH	;SEEK WITH VERIFY
;
;
;
;	THE FOLLOWING RAM LOCATIONS ARE REQ
;
TRKNO	DB	0H	
TEMP	DB	0H	
TEMP1	DB	0H	
IXSAV	DW	0000H	
	DS	30H
STACK	EQU	$
;END

